﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Enterprise.Data
{
    public class DataMap
    {
        // Fields
        private BindingFlags _fieldFlags = (BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        private List<MemberMapping> _map = new List<MemberMapping>();
        private BindingFlags _propertyFlags = (BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance);
        private Type _sourceType;
        private Type _targetType;

        // Methods
        public DataMap(Type sourceType, Type targetType)
        {
            this._sourceType = sourceType;
            this._targetType = targetType;
        }

        public void AddFieldMapping(string sourceField, string targetField)
        {
            this._map.Add(new MemberMapping(this._sourceType.GetField(sourceField, this._fieldFlags), this._targetType.GetField(targetField, this._fieldFlags)));
        }

        public void AddFieldToPropertyMapping(string sourceField, string targetProperty)
        {
            this._map.Add(new MemberMapping(this._sourceType.GetField(sourceField, this._fieldFlags), this._targetType.GetProperty(targetProperty, this._propertyFlags)));
        }

        public void AddPropertyMapping(string sourceProperty, string targetProperty)
        {
            this._map.Add(new MemberMapping(this._sourceType.GetProperty(sourceProperty, this._propertyFlags), this._targetType.GetProperty(targetProperty, this._propertyFlags)));
        }

        public void AddPropertyToFieldMapping(string sourceProperty, string targetField)
        {
            this._map.Add(new MemberMapping(this._sourceType.GetProperty(sourceProperty, this._propertyFlags), this._targetType.GetField(targetField, this._fieldFlags)));
        }

        internal List<MemberMapping> GetMap()
        {
            return this._map;
        }

        // Nested Types
        internal class MemberMapping
        {
            // Fields
            private MemberInfo _from;
            private MemberInfo _to;

            // Methods
            public MemberMapping(MemberInfo fromMember, MemberInfo toMember)
            {
                this._from = fromMember;
                this._to = toMember;
            }

            // Properties
            public MemberInfo FromMember
            {
                get
                {
                    return this._from;
                }
            }

            public MemberInfo ToMember
            {
                get
                {
                    return this._to;
                }
            }
        }
    }


}
